using System.Collections;
using System.Collections.Generic;
using Unity.Android.Gradle.Manifest;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;

public class Player : MonoBehaviour
{
    private Animator _animator;
    private Rigidbody _rb;

    private CapsuleCollider _capsuleCollider = null;

    [Tooltip("移动速度")]
    [SerializeField]
    private float walkSpeed;
    [SerializeField]
    private float runSpeed;

    [Space(15)]
    [Tooltip("落地物理检测")]
    [SerializeField]
    private LayerMask groundLayer;

    [SerializeField]
    private float groundCheckDistance = 1f;
    [SerializeField]
    private float groundCheckRadius = 0.5f;

    [SerializeField]
    private float jumpHeight = 10f;

    private float _currentSpeed;

    private float _horizontal;
    private float _vertical;

    private Vector3 _direction;

    private bool _isRunning = false;
    /// <summary>
    /// 是否处于地面上
    /// </summary>
    private bool _isGround = true;

    private bool _isLockingTarget = false;

    
    #region 劈砍动作相关
    /// <summary>
    /// 劈砍是否可以连击
    /// </summary>
    private bool _canSlashCombo = false;
    /// <summary>
    /// 是否在连击过程中
    /// </summary>
    private bool _slashComboInProgress = false;
    /// <summary>
    /// 连击计时器
    /// </summary>
    private float _slashComboTimer = 0f;

    [Space(10)]
    [Tooltip("劈砍动作连击时间窗口")]
    [SerializeField]
    private float slashComboWindow = 0.2f;
    /// <summary>
    /// 当前连击的步数
    /// </summary>
    private int _slashComboStep = 0;
    #endregion

    #region 踢腿动作相关
    /// <summary>
    /// 劈砍是否可以连击
    /// </summary>
    private bool _canKickCombo = false;
    /// <summary>
    /// 是否在连击过程中
    /// </summary>
    private bool _kickComboInProgress = false;
    /// <summary>
    /// 连击计时器
    /// </summary>
    private float _kickComboTimer = 0f;

    [Space(10)]
    [Tooltip("踢腿动作连击时间窗口")]
    [SerializeField]
    private float kickComboWindow = 0.2f;
    /// <summary>
    /// 当前连击的步数
    /// </summary>
    private int _kickComboStep = 0;
    #endregion

    #region 技能输入队列相关
    private Queue<string> inputQueue = new();
    private bool canExecuteNextAttack = false;
    #endregion

    private void Awake() {
        _animator = GetComponent<Animator>();
        _animator.applyRootMotion = false;

        _rb = GetComponent<Rigidbody>();
        _capsuleCollider = GetComponent<CapsuleCollider>();
        walkSpeed = 2;
        runSpeed = 4.5f;
    }

    // Start is called before the first frame update
    void Start()
    {
        
    }

    public void SetAnimatorFloat(string key,float v) {
        if(_animator == null) return;
        _animator.SetFloat(key,v);
    }

    // Update is called once per frame
    void Update()
    {
        _horizontal = Input.GetAxis("Horizontal");
        _vertical = Input.GetAxis("Vertical");
        if(Input.GetKeyDown(KeyCode.LeftShift)) {
            _isRunning = true;
        }
        if(Input.GetKeyUp(KeyCode.LeftShift)) {
            _isRunning = false;
        }

        if(_isGround && Input.GetKeyDown(KeyCode.Space)) {
            _animator.SetTrigger("jump");
            Debug.Log("施加力跳跃");
            _rb.AddForce(Vector3.up * 3,ForceMode.Impulse);
        }

        if(Input.GetKeyDown(KeyCode.Z)) {
            // 锁定攻击目标
            _isLockingTarget = !_isLockingTarget;
        }

        SlashUpdateCheck();
        HandleComboQueue();

    }

    private void HandleComboQueue() {
        if(CanExecuteNextAttack()) {
            if(inputQueue.Count > 0) {
                string nextAttack = inputQueue.Dequeue();
                doAttack(nextAttack);
            }
        }
    }

    private bool CanExecuteNextAttack() {
        AnimatorStateInfo stateInfo = _animator.GetCurrentAnimatorStateInfo(0);
        List<int> slashList = new List<int>();
        slashList.Add(Animator.StringToHash("slash"));
        slashList.Add(Animator.StringToHash("slash2"));
        slashList.Add(Animator.StringToHash("slash_heavy"));

        int shortNameHash = stateInfo.shortNameHash;

        if(slashList.IndexOf(shortNameHash) >= 0) {
            return stateInfo.normalizedTime >= 0.9f && !_animator.IsInTransition(0);
        }
        return true;
    }

    private void doAttack(string attack) {
        if(attack == "slash") {
            if(_slashComboStep == 0) {
                _animator.SetTrigger("slash");
                _slashComboStep = 1;
                _slashComboInProgress = true;
                _slashComboTimer = 0f;
            } else {
                _animator.SetTrigger("slash2");
                _slashComboStep = 2;
                _slashComboTimer = 0;
            }
        } else if(attack == "slash_heavy") {
            if(_slashComboStep == 2) {
                _animator.SetTrigger("slash_heavy");
                _slashComboStep = 3;
                _slashComboTimer = 0f;
            }
        }
    }

    private void SlashUpdateCheck() {
        if(Input.GetKeyDown(KeyCode.X)) {
            inputQueue.Enqueue("slash");
        }
        if(Input.GetKeyDown(KeyCode.J)) {
            inputQueue.Enqueue("slash_heavy");
        }

        if(_slashComboInProgress) {
            _slashComboTimer += Time.deltaTime;
            if(_slashComboTimer > slashComboWindow) {
                ResetSlashCombo();
            }
        }
    }

    private void ResetSlashCombo() {
        _slashComboStep = 0;
        _slashComboTimer = 0f;
        _slashComboInProgress = false;
    }

    /// <summary>
    /// 检测主角是否处于地面上
    /// </summary>
    /// <returns></returns>
    private void CheckIsGround() {
        if(_capsuleCollider == null) return;
        Vector3 capsuleBottom = _capsuleCollider.bounds.center - new Vector3(0,_capsuleCollider.bounds.extents.y,0);
        _isGround = Physics.CheckSphere(capsuleBottom,groundCheckRadius,groundLayer);
        Debug.Log("isGround is " + _isGround);
        Debug.DrawRay(capsuleBottom,Vector3.down,Color.red);
    }

    void FixedUpdate() {
        Vector3 input = new(_horizontal,0,_vertical);
        _direction = input.normalized;

        if(_isLockingTarget) {
            _animator.SetTrigger("lock");
        } else {
            _animator.SetTrigger("exit_lock");
        }

        if(_direction.magnitude > 0) {
            if(!_isLockingTarget) {
                transform.rotation = Quaternion.LookRotation(_direction,Vector3.up);
            }

            Vector3 currentPosition = transform.position;
            if(_isRunning) {
                currentPosition += runSpeed * Time.deltaTime * _direction;
            } else {
                currentPosition += Time.deltaTime * walkSpeed * _direction;
            }

            _rb.MovePosition(currentPosition);
        }
        if(!_isLockingTarget) {
            if(_isRunning) {
                _currentSpeed = _direction.magnitude * runSpeed;
            } else {
                _currentSpeed = _direction.magnitude * walkSpeed;
            }
            _animator.SetFloat("speed",_currentSpeed);
        } else {
            float hSpeed;
            float vSpeed;

            if(_isRunning) {
                hSpeed = _direction.x * runSpeed;
                vSpeed = _direction.z * runSpeed;
            } else {
                hSpeed = _direction.x * walkSpeed;
                vSpeed = _direction.z * walkSpeed;
            }

            _animator.SetFloat("hs",hSpeed);
            _animator.SetFloat("vs",vSpeed);
        }

        CheckIsGround();   
    }
}
